package com.ki.erp.util;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.bson.Document;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class JsonToAggregationConverter {

    public static List<AggregationOperation> convert(String json) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        // 解析JSON为List<Map<String, Object>>
        List<Map<String, Object>> stages = objectMapper.readValue(
                json, new TypeReference<List<Map<String, Object>>>() {
                });

        List<AggregationOperation> operations = new ArrayList<>();
        for (Map<String, Object> stage : stages) {
            // 每个阶段应仅包含一个聚合操作符（如$match、$project）
            for (Map.Entry<String, Object> entry : stage.entrySet()) {
                String operator = entry.getKey();
                Object value = entry.getValue();
                // 递归转换嵌套的Map和List为MongoDB的Document类型
                Document document = new Document(operator, convertValue(value));
                operations.add(new CustomAggregationOperation(document));
            }
        }
        return operations;
    }

    // 递归转换嵌套结构：Map → Document，List → ArrayList<Object>
    private static Object convertValue(Object value) {
        if (value instanceof Map) {
            Document doc = new Document();
            ((Map<?, ?>) value).forEach((k, v) ->
                    doc.put(k.toString(), convertValue(v)));
            return doc;
        } else if (value instanceof List) {
            List<Object> list = new ArrayList<>();
            ((List<?>) value).forEach(item ->
                    list.add(convertValue(item)));
            return list;
        }
        return value;
    }

    // 自定义聚合操作，直接包装MongoDB原生Document
    private static class CustomAggregationOperation implements AggregationOperation {
        private final Document document;

        public CustomAggregationOperation(Document document) {
            this.document = document;
        }

        @Override
        public Document toDocument(AggregationOperationContext context) {
            return context.getMappedObject(document);
        }
    }
}